package middleware;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.StringTokenizer;
import java.util.Random;

// class to generate and return the refresh functions (RF)
public class RFController {
	private ArrayList<ArrayList<String>> orderData;
	private ArrayList<ArrayList<String>> lineItemData;
	private ArrayList<Integer> deleteData;

	public RFController() {
		orderData = new ArrayList<ArrayList<String>>();
		lineItemData = new ArrayList<ArrayList<String>>();
		deleteData = new ArrayList<Integer>();
	}

	/**
	 * Generates the queries for refresh function 1.
	 * @param fileNr indicates the file number to be fetched in /refreshdata.
	 * @return Set of update strings to be executed.
	 */
	public ArrayList<String> generateRF1(int fileNr) {
		
		ArrayList<String> stringSet = new ArrayList<String>();
		
		this.readOrderData(fileNr);
		this.readLineItemData(fileNr);
		int lineItemPosition = 0;
		
		// loop over orders
		// and fetch corresponding lineitems
		for (int i = 0; i < orderData.size(); i++) {
			String currentOrder = orderData.get(i).get(0);
			
			StringBuilder strBuilder = new StringBuilder();
			strBuilder.append("INSERT INTO ORDERS VALUES (");
			
			for (int j = 0; j < 9; j++) {
				strBuilder.append("'");
				strBuilder.append(orderData.get(i).get(j));
				strBuilder.append("',");
				
			}
			strBuilder.deleteCharAt(strBuilder.length() - 1);
			strBuilder.append(");");
			
			strBuilder.append("INSERT INTO LINEITEM VALUES ");
			for (; lineItemPosition < lineItemData.size() && lineItemData.get(lineItemPosition).get(0).equals(currentOrder); lineItemPosition++ ) {
				strBuilder.append("(");
				for (int j = 0; j < 16; j++) {
					strBuilder.append("'");
					strBuilder.append(lineItemData.get(lineItemPosition).get(j));					
					strBuilder.append("',");
				}
				strBuilder.deleteCharAt(strBuilder.length() - 1);
				strBuilder.append("),");
			}
			strBuilder.deleteCharAt(strBuilder.length() - 1);			
			strBuilder.append(";");
			stringSet.add(strBuilder.toString());
			
		}
		return stringSet;
	}
	
	/**
	 * Generates the queries for refresh function 2.
	 * @param fileNr indicates the file number to be fetched in /refreshdata.
	 * @return Set of update strings to be executed.
	 */
	public ArrayList<String> generateRF2(int fileNr) {
		this.readDeleteData(fileNr);
		ArrayList<String> stringSet = new ArrayList<String>();	
		
		for (int i = 0; i < deleteData.size(); i++) {
			StringBuilder strBuilder = new StringBuilder();	
			strBuilder.append("DELETE FROM LINEITEM WHERE L_ORDERKEY = ");
			strBuilder.append(deleteData.get(i));
			strBuilder.append("; ");
			strBuilder.append("DELETE FROM ORDERS WHERE O_ORDERKEY = ");
			strBuilder.append(deleteData.get(i));
			strBuilder.append("; ");
			stringSet.add(strBuilder.toString());
		}

		return stringSet;
	}

	/**
	 * Reads and processes all the order data and stores into orderData.
	 * @param fileNr indicates the file number to be fetched in /refreshdata.
	 */
	private void readOrderData(int fileNr) {
		FileInputStream fstream = null;
		String line;

		try {
			fstream = new FileInputStream("refreshdata/orders.tbl.u" + fileNr);
		} catch (FileNotFoundException e) {
			System.out.println(e.getMessage());
		}

		DataInputStream in = new DataInputStream(fstream);

		try {
			while (in.available() != 0) {
				line = in.readLine();
				ArrayList<String> als = new ArrayList<String>();
				StringTokenizer st = new StringTokenizer(line, "|");
				while (st.hasMoreTokens()) {
					als.add(st.nextToken());
				}
				orderData.add(als);
			}
			in.close();
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}		
	}

	/**
	 * Reads and processes all the lineitem data and stores into lineItemData.
	 * @param fileNr indicates the file number to be fetched in /refreshdata.
	 */
	private void readLineItemData(int fileNr) {
		FileInputStream fstream = null;
		String line;

		try {
			fstream = new FileInputStream("refreshdata/lineitem.tbl.u" + fileNr);
		} catch (FileNotFoundException e) {
			System.out.println(e.getMessage());
		}

		DataInputStream in = new DataInputStream(fstream);

		try {
			while (in.available() != 0) {
				line = in.readLine();
				ArrayList<String> als = new ArrayList<String>();
				StringTokenizer st = new StringTokenizer(line, "|");
				while (st.hasMoreTokens()) {
					als.add(st.nextToken());
				}
				lineItemData.add(als);
			}
			in.close();
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
	}
	/**
	 * Reads and processes all the deletion data and stores into deleteData.
	 * @param fileNr indicates the file number to be fetched in /refreshdata.
	 */
	private void readDeleteData(int fileNr) {
		FileInputStream fstream = null;
		String line;

		try {
			fstream = new FileInputStream("refreshdata/delete." + fileNr);
		} catch (FileNotFoundException e) {
			System.out.println(e.getMessage());
		}

		DataInputStream in = new DataInputStream(fstream);

		try {
			while (in.available() != 0) {
				line = in.readLine();
				deleteData.add(new Integer(line));
			}
			in.close();
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}		
	}
}
